package anaydis.animation.sort;

import anaydis.sort.Sorter;
import anaydis.animation.core.AnimationController;
import com.sun.istack.internal.NotNull;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

public class MergeSortAnimation
        extends SortAnimation
{
    private List<Integer> aux;
    private int copyFrom, copyTo;
    private float copyStep;
    private boolean direction; // true > original-to-aux ;  false > aux-to-original

    public MergeSortAnimation(@NotNull final Sorter sorter)
    {
        super(sorter);
    }

    @Override protected void fillArray()
    {
        super.fillArray();

        aux = new ArrayList<Integer>(array.size());

        for(Integer dummy : array) {
            aux.add(0);
        }
    }

    @Override protected void unmarkAll()
    {
        copyFrom = copyTo = -1;
        copyStep = 0;
        super.unmarkAll();
    }

    @Override protected void paintArray(@NotNull final Graphics2D graphics, @NotNull final List<Integer> array,
                                        int slotOffset, int yoffset, int height,
                                        int swapFrom, int swapTo, int cmpFrom, int cmpTo)
    {
        super.paintArray(graphics, array, slotOffset, yoffset, height / 2, -1, -1, -1, -1);

        super.paintArray(graphics, aux, slotOffset, yoffset + height / 2, height / 2, -1, -1, cmpFrom, cmpTo);

        drawCopy(graphics, copyStep, copyFrom, copyTo, slotOffset, height/2);
    }

    private void drawCopy(Graphics2D g, float step, int from, int to, int offset, int height)
    {
        if (from != -1 && to != -1) {
            final float dispX = (to - from) * step;
            final float dispY = height * step;
            int x = Math.round(SPACE + offset * (from + dispX));
            int y = Math.round(direction ? dispY : height - dispY);
            drawSlot(g, direction ? array : aux, TMAIN, LIGHT_TMAIN, x, from, offset, y, height);
        }
    }

    @Override public void copy(int from, int to, boolean copyToAux)
    {
        if (speed == AnimationController.MAX_SPEED) {
            doSleep(1000);
        }
        else {
            direction = copyToAux;
            copyFrom = from;
            copyTo = to;
            animating = true;
            int time = 1000;
            int steps = (AnimationController.MAX_SPEED - speed) / 5 + 1;
            int timeslot = time / steps;
            for (int step = 1; step <= steps; step++) {
                copyStep = (float) step / steps;
                doSleep(timeslot);
                time -= timeslot;
            }
            if (time > 0) {
                doSleep(time);
            }

            copyFrom = copyTo = -1;
            animating = false;
        }

        if(copyToAux) {
            aux.set(to, array.get(from));
            array.set(from, 0);
        } else {
            array.set(to, aux.get(from));
            aux.set(from, 0);
        }
    }
}
